package zero.clean.beetlsql.sb;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.beetl.core.resource.ClasspathResourceLoader;
import org.beetl.sql.clazz.kit.StringKit;
import org.beetl.sql.core.ConditionalSQLManager;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PropertiesLoaderUtils;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;


@Data
@Slf4j
public class BeetlSqlConfig {
    public static final String PREFIX = "beetlsql";

    private static final String configFileName = "beetlsql.properties";

    Environment env = null;
    Properties properties = null;

    public BeetlSqlConfig(Environment env) {
        this.env = env;
        init();
    }


    Map<String, SQLManagerConfig> configs = new HashMap<>();

    public void init() {

        SQLManagerConfig defaultConfig = SQLManagerConfig.initDefault(env);
        String[] allSqlManangerNames = null;
        boolean standaloneConfigFile = false;
        if (StringKit.isBlank(env.getProperty("beetlsql.sqlManagers"))) {
            standaloneConfigFile = new ClasspathResourceLoader().exist(configFileName);
            if (!standaloneConfigFile) {
                throw new IllegalArgumentException("缺少 beetlsql.sqlManagers 配置");
            }
        }
        if (standaloneConfigFile) {
            log.info("using standalone app-beetlsql-configs");
            try {
                Resource resource = new ClassPathResource(configFileName);
                properties = PropertiesLoaderUtils.loadProperties(resource);
                allSqlManangerNames = properties.getProperty("beetlsql.sqlManagers").split(",");
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        } else {
            allSqlManangerNames = env.getProperty("beetlsql.sqlManagers").split(",");
        }


        for (String s : allSqlManangerNames) {
            SQLManagerConfig sqlManagerConfig = null;
            if (standaloneConfigFile) {
                sqlManagerConfig = new SQLManagerConfig(properties, s, defaultConfig);
            } else {
                sqlManagerConfig = new SQLManagerConfig(env, s, defaultConfig);
            }

            if (sqlManagerConfig.isDisable()) {
                continue;
            }
            configs.put(s, sqlManagerConfig);
        }

    }

    @Data
    public static class SQLManagerConfig {
        String basePackage = null;// 配置beetlsql.daoSuffix来自动扫描com包极其子包下的所有以Dao结尾的Mapper类
        String daoSuffix = null;// 通过类后缀 来自动注入Dao
        String sqlPath = null;// 存放sql文件的根目录
        String sqlFileCharset = null;// 文件的字符集

        String nameConversion = null;// 数据库和javapojo的映射关系
        String dbStyle = null; // 何种数据库
        boolean dev = false;
        String ds = null;

        String dynamicSqlManager;
        String dynamicCondition;
        String threadlocal;
        String interceptor;

        boolean disable = false;


        public SQLManagerConfig() {
        }

        public static SQLManagerConfig initDefault(Environment env) {

            String prefix = PREFIX + "._default";
            String basePackage = env.getProperty(prefix + ".basePackage", "com");
            String daoSuffix = env.getProperty(prefix + ".daoSuffix", "Mapper");
            String sqlPath = env.getProperty(prefix + ".sqlPath", "sql");
            String sqlFileCharset = env.getProperty(prefix + ".sqlFileCharset", Charset.defaultCharset().name());
            String nameConversion = env.getProperty(prefix + ".nameConversion", "org.beetl.sql.core.UnderlinedNameConversion");
            String dbStyle = env.getProperty(prefix + ".dbStyle", "org.beetl.sql.core.db.MySqlStyle");
            boolean dev = env.getProperty(prefix + ".dev", Boolean.class, true);
            String interceptor = env.getProperty(prefix + ".interceptor", String.class);
            SQLManagerConfig defaultConfig = new SQLManagerConfig();
            defaultConfig.setBasePackage(basePackage);
            defaultConfig.setDaoSuffix(daoSuffix);
            defaultConfig.setSqlPath(sqlPath);
            defaultConfig.setNameConversion(nameConversion);
            defaultConfig.setDbStyle(dbStyle);
            defaultConfig.setDev(dev);
            defaultConfig.setSqlFileCharset(sqlFileCharset);
            defaultConfig.setInterceptor(interceptor);
            return defaultConfig;

        }


        public SQLManagerConfig(Environment env, String sqlManagerName, SQLManagerConfig defaultConfig) {
            String prefix = PREFIX + "." + sqlManagerName;
            String disableOnPropertyName = env.getProperty(prefix + ".disableOn");
            if (disableOnPropertyName != null) {
                //当存在某属性的时候，此sqlManager配置不生效
                boolean isExist = env.containsProperty(disableOnPropertyName);
                if (isExist) {
                    disable = true;
                    return;
                }
            }
            dynamicSqlManager = env.getProperty(prefix + ".dynamic");
            if (!StringKit.isEmpty(dynamicSqlManager)) {
                dynamicCondition = env.getProperty(prefix + ".dynamic.condition");
                if (StringKit.isEmpty(dynamicCondition)) {
                    //默认
                    dynamicCondition = ConditionalSQLManager.DefaultConditional.class.getName();
                }
                basePackage = env.getProperty(prefix + ".basePackage", defaultConfig.getBasePackage());
                daoSuffix = env.getProperty(prefix + ".daoSuffix", defaultConfig.getDaoSuffix());
                dev = env.getProperty(prefix + ".dev", Boolean.class, defaultConfig.isDev());
                return;
            }
            threadlocal = env.getProperty(prefix + ".threadlocal");

            if (dynamicSqlManager != null && threadlocal != null) {
                throw new IllegalArgumentException("dynamic和threadlocal 只能二选一");
            }

            basePackage = env.getProperty(prefix + ".basePackage", defaultConfig.getBasePackage());
            daoSuffix = env.getProperty(prefix + ".daoSuffix", defaultConfig.getDaoSuffix());
            sqlPath = env.getProperty(prefix + ".sqlPath", defaultConfig.getSqlPath());
            sqlFileCharset = env.getProperty(prefix + ".sqlFileCharset", defaultConfig.getSqlFileCharset());
            nameConversion = env.getProperty(prefix + ".nameConversion", defaultConfig.getNameConversion());
            dbStyle = env.getProperty(prefix + ".dbStyle", defaultConfig.getDbStyle());
            dev = env.getProperty(prefix + ".dev", Boolean.class, defaultConfig.isDev());
            ds = env.getProperty(prefix + ".ds");
            interceptor = env.getProperty(prefix + ".interceptor", defaultConfig.getInterceptor());

            if (!(dynamicSqlManager != null || threadlocal != null)) {
                if (ds == null) {
                    throw new NullPointerException(prefix + ".ds 不能为空");
                }
            }

        }


        public SQLManagerConfig(Properties env, String sqlManagerName, SQLManagerConfig defaultConfig) {
            String prefix = PREFIX + "." + sqlManagerName;
            String disableOnPropertyName = env.getProperty(prefix + ".disableOn");
            if (disableOnPropertyName != null) {
                //当存在某属性的时候，此sqlManager配置不生效
                boolean isExist = env.contains(disableOnPropertyName);
                if (isExist) {
                    disable = true;
                    return;
                }
            }
            dynamicSqlManager = env.getProperty(prefix + ".dynamic");
            if (!StringKit.isEmpty(dynamicSqlManager)) {
                dynamicCondition = env.getProperty(prefix + ".dynamic.condition");
                if (StringKit.isEmpty(dynamicCondition)) {
                    //默认
                    dynamicCondition = ConditionalSQLManager.DefaultConditional.class.getName();
                }
                basePackage = env.getProperty(prefix + ".basePackage", defaultConfig.getBasePackage());
                daoSuffix = env.getProperty(prefix + ".daoSuffix", defaultConfig.getDaoSuffix());
                String strDev = env.getProperty(prefix + ".dev", String.valueOf(defaultConfig.isDev()));
                dev = Boolean.valueOf(strDev);
                return;
            }
            threadlocal = env.getProperty(prefix + ".threadlocal");

            if (dynamicSqlManager != null && threadlocal != null) {
                throw new IllegalArgumentException("dynamic和threadlocal 只能二选一");
            }

            basePackage = env.getProperty(prefix + ".basePackage", defaultConfig.getBasePackage());
            daoSuffix = env.getProperty(prefix + ".daoSuffix", defaultConfig.getDaoSuffix());
            sqlPath = env.getProperty(prefix + ".sqlPath", defaultConfig.getSqlPath());
            sqlFileCharset = env.getProperty(prefix + ".sqlFileCharset", defaultConfig.getSqlFileCharset());
            nameConversion = env.getProperty(prefix + ".nameConversion", defaultConfig.getNameConversion());
            dbStyle = env.getProperty(prefix + ".dbStyle", defaultConfig.getDbStyle());
            String strDev = env.getProperty(prefix + ".dev", String.valueOf(defaultConfig.isDev()));
            dev = Boolean.valueOf(strDev);
            ds = env.getProperty(prefix + ".ds");
            interceptor = env.getProperty(prefix + ".interceptor", defaultConfig.getInterceptor());

            if (!(dynamicSqlManager != null || threadlocal != null)) {
                if (ds == null) {
                    throw new NullPointerException(prefix + ".ds 不能为空");
                }
            }

        }
    }
}
